package com.example.springtransaction.controller;

import com.example.springtransaction.model.LogInfo;
import com.example.springtransaction.model.Userinfo;
import com.example.springtransaction.service.LogService;
import com.example.springtransaction.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 23735
 * Date: 2023-03-16
 * Time: 23:09
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private LogService logService;
//  注入事务管理器
    @Autowired
    private DataSourceTransactionManager transactionManager;
//    定义事务属性
    @Autowired
    private TransactionDefinition transactionDefinition;

//    编程式事务(手动开启事务)
    @RequestMapping("/add1")
    public int add1(String name, String address){
//        获得事务(开启事务)
        TransactionStatus transactionStatus=
                transactionManager.getTransaction(transactionDefinition);
//      执行业务代码
        Userinfo userinfo=new Userinfo();
        userinfo.setName(name);
        userinfo.setAddress(address);
        int result=userService.add(userinfo);
        log.info("受影响的行数: "+result);
//        回滚事务
//        transactionManager.rollback(transactionStatus);
//        提交事务
        transactionManager.commit(transactionStatus);
        return result;
    }

//  声明式事务(自动开启事务)
    @Transactional
    @RequestMapping("/add2")
    public int add2(String name, String address){
//      执行业务代码
        Userinfo userinfo=new Userinfo();
        userinfo.setName(name);
        userinfo.setAddress(address);
        int result=userService.add(userinfo);
        log.info("受影响的行数: "+result);
//      出现异常自动回滚事务
//        注意当手动捕获异常时不会回滚
//        解决:
//        ①把异常往上抛
//        ②手动回滚
        try{
            int num=10/0;
        }catch (ArithmeticException e){
//            方法一:异常往上抛
//            throw e;
//            方法二:手动回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            log.info("捕获了一个异常: "+e.getMessage());
        }
        return result;
    }


    //  事务超时时间
    @Transactional(timeout = 1) // 设置事务的超时时间, 即如果事务经过1s还未执行完那么进行回滚
    @RequestMapping("/add3")
    public int add3(String name, String address) throws InterruptedException {
        Thread.sleep(2000);
//      执行业务代码
        Userinfo userinfo=new Userinfo();
        userinfo.setName(name);
        userinfo.setAddress(address);
        int result=userService.add(userinfo);
        log.info("受影响的行数: "+result);
        return result;
    }



    //    支持当前事务
    //    事务传播机制中的 required
//    当日志添加时出现异常, 用户添加成功的数据也回滚了
    @Transactional(propagation = Propagation.REQUIRED)
    @RequestMapping("/add4")
    public int add4(String name, String address){
        Userinfo userinfo=new Userinfo();
        userinfo.setName(name);
        userinfo.setAddress(address);
        int result=userService.add(userinfo);
        log.info("受影响的行数: "+result);
        LogInfo logInfo=new LogInfo();
        logInfo.setTitle("添加用户");
        logInfo.setContent("添加用户结果为: "+result);
        int logResult=logService.add(logInfo);
        return result;
    }


    //    logService 和 userService 的 事务传播机制设置为不支持当前事务
    //    事务传播机制中的 NOT_SUPPORTED
//    当日志添加时出现异常, 用户添加成功的数据不会回滚
    @Transactional
    @RequestMapping("/add5")
    public int add5(String name, String address){
        Userinfo userinfo=new Userinfo();
        userinfo.setName(name);
        userinfo.setAddress(address);
        int result=userService.add(userinfo);
        log.info("受影响的行数: "+result);
        LogInfo logInfo=new LogInfo();
        logInfo.setTitle("添加用户");
        logInfo.setContent("添加用户结果为: "+result);
        int logResult=logService.add(logInfo);
        return result;
    }


    //    logService 和 userService 的 事务传播机制设置为 Required_new
//    当前不存在事务则新建, 存在事务则挂起
//    当日志添加时出现异常回滚, 用户添加成功的数据不会回滚
    @Transactional
    @RequestMapping("/add6")
    public int add6(String name, String address){
        Userinfo userinfo=new Userinfo();
        userinfo.setName(name);
        userinfo.setAddress(address);
        int result=userService.add(userinfo);
        log.info("受影响的行数: "+result);
        LogInfo logInfo=new LogInfo();
        logInfo.setTitle("添加用户");
        logInfo.setContent("添加用户结果为: "+result);
        int logResult=logService.add(logInfo);
        return result;
    }

    //    logService 和 userService 的 事务传播机制设置为 nested
    //    当前存在事务则嵌套到当前事务中执行
    //    当前不存在事务则执行结果与 required 相同
    //    当日志添加时出现异常回滚, 用户添加成功的数据不会回滚
    @Transactional(propagation = Propagation.NESTED)
    @RequestMapping("/add7")
    public int add7(String name, String address){
        Userinfo userinfo=new Userinfo();
        userinfo.setName(name);
        userinfo.setAddress(address);
        return userService.save(userinfo);
    }


    /**
     *  外部出现异常回滚时, 内部一定回滚
     * @return
     */
    @Transactional(propagation = Propagation.NESTED)
    @RequestMapping("/add8")
    public int add8(){
        Userinfo userinfo=new Userinfo();
        userinfo.setName("name");
        userinfo.setAddress("address");
        userService.save8(userinfo);
        userService.save8(userinfo);
        userService.save8(userinfo);
        userService.save8(userinfo);
        userService.save8(userinfo);
        userService.save8(userinfo);
        userService.save8(userinfo);
        userService.save8(userinfo);
        int val = 10 / 0;
        return -1;
    }



    /**
     *  外部出现异常回滚时, 内部一定回滚
     * @return
     */
    @Transactional(propagation = Propagation.NESTED)
    @RequestMapping("/add9")
    public int add9(){
        Userinfo userinfo=new Userinfo();
        userinfo.setName("name");
        userinfo.setAddress("address");
        userService.save8(userinfo);
        userService.save9(userinfo);

//        try {
//            userService.save10(userinfo);
//        } catch (Exception e) {
//        }
        userService.save11(userinfo);
//        int val = 10 / 0;
        return -1;

    }
}
